Current Weather Quicklooks#
Code to Create Plots#
Show code cell source
import sage_data_client
from bokeh.models.formatters import DatetimeTickFormatter
import hvplot.pandas
import hvplot.xarray
import holoviews as hv
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import xarray as xr
import matplotlib.pyplot as plt
from metpy.plots import USCOUNTIES
import metpy.calc as mpcalc
import act
import numpy as np
import pandas as pd
import warnings
from bokeh.models import DatetimeTickFormatter
def apply_formatter(plot, element):
plot.handles['xaxis'].formatter = DatetimeTickFormatter(hours='%m/%d/%Y \n %H:%M',
minutes='%m/%d/%Y \n %H:%M',
hourmin='%m/%d/%Y \n %H:%M',
days='%m/%d/%Y \n %H:%M',
months='%m/%d/%Y \n %H:%M')
xr.set_options(keep_attrs=True)
warnings.filterwarnings("ignore")
hv.extension("bokeh")
# Dictionary for renaming to standard names
variable_rename_dict = {'wxt.env.humidity':'relative_humidity',
'wxt.env.pressure':'air_pressure',
'wxt.env.temp':'air_temperature',
'wxt.heater.temp':'heater_temperature',
'wxt.heater.volt':'heater_voltage',
'wxt.rain.accumulation':'rain_accumulation',
'wxt.wind.direction':'wind_direction',
'wxt.wind.speed':'wind_speed',
'sys.gps.lat':'latitude',
'sys.gps.lon':'longitude',
}
# Dictionary for units that are missing
units_dict = {'wxt.env.temp': 'degC',
'wxt.env.pressure':'hPa',
'wxt.env.humidity':'percent',
'wxt.wind.speed':'m/s',
'wxt.wind.direction':'degrees'}
def generate_data_array(df, variable, rename_variable_dict=variable_rename_dict):
new_variable_name = rename_variable_dict[variable]
df_variable= df.loc[df.name == variable]
ds = df_variable.to_xarray().rename({'value':new_variable_name,
'timestamp':'time',
'meta.vsn':'node'})
ds[new_variable_name].attrs['units'] = df_variable['meta.units'].values[0]
ds['time'] = pd.to_datetime(ds.time)
ds.attrs['datastream'] = ds.node.values[0]
return ds[[new_variable_name]]
def generate_dataset(df, variables, rename_variable_dict=variable_rename_dict):
reindexed = df.set_index(['meta.vsn', 'timestamp'])
return xr.merge([generate_data_array(reindexed, variable) for variable in variables])
# Query and load for n numbder of days
wxt_df = sage_data_client.query(
start="-12h",
filter={
"sensor": "vaisala-wxt536",
"name": "wxt.env.*"
}
)
wxt_df1 = sage_data_client.query(
start="-12h",
filter={
"sensor": "vaisala-wxt536",
"name": "wxt.wind.*"
}
)
wxt_df = pd.concat([wxt_df, wxt_df1])
# Discover what variables we have and what to load into xarray
wxt_variables = wxt_df.name.unique()
wxt_df['meta.units'] = wxt_df.name.map(units_dict)
wxt_ds = generate_dataset(wxt_df, wxt_variables).squeeze().metpy.parse_cf()
wxt_ds['air_dewpoint_temperature'] = mpcalc.dewpoint_from_relative_humidity(wxt_ds.air_temperature, wxt_ds.relative_humidity)
# Resample to 1 minute freqency
minute_ds = wxt_ds.resample(time='1T').mean()
plots = []
temp_plot = wxt_ds.air_temperature.hvplot(color='red',
label='Air Temperature (degC)')
dewp_plot = wxt_ds.air_dewpoint_temperature.hvplot(color='green',
label='Dewpoint Temperature (degC)')
plots.append((temp_plot * dewp_plot).opts(hooks=[apply_formatter]))
meteogram_variables = ['wind_speed', 'wind_direction']
for variable in meteogram_variables:
plots.append((wxt_ds[variable].hvplot.line(label='10 Hz Data') *
minute_ds[variable].hvplot.line(label='1 Minute Data')).opts(hooks=[apply_formatter]))
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/tmp/ipykernel_3990/3820344723.py in ?()
84
85 # Discover what variables we have and what to load into xarray
86 wxt_variables = wxt_df.name.unique()
87 wxt_df['meta.units'] = wxt_df.name.map(units_dict)
---> 88 wxt_ds = generate_dataset(wxt_df, wxt_variables).squeeze().metpy.parse_cf()
89 wxt_ds['air_dewpoint_temperature'] = mpcalc.dewpoint_from_relative_humidity(wxt_ds.air_temperature, wxt_ds.relative_humidity)
90
91 # Resample to 1 minute freqency
/tmp/ipykernel_3990/3820344723.py in ?(df, variables, rename_variable_dict)
61 def generate_dataset(df, variables, rename_variable_dict=variable_rename_dict):
---> 62 reindexed = df.set_index(['meta.vsn', 'timestamp'])
63 return xr.merge([generate_data_array(reindexed, variable) for variable in variables])
/usr/share/miniconda3/envs/instrument-cookbooks-dev/lib/python3.10/site-packages/pandas/util/_decorators.py in ?(*args, **kwargs)
327 msg.format(arguments=_format_argument_list(allow_args)),
328 FutureWarning,
329 stacklevel=find_stack_level(),
330 )
--> 331 return func(*args, **kwargs)
/usr/share/miniconda3/envs/instrument-cookbooks-dev/lib/python3.10/site-packages/pandas/core/frame.py in ?(self, keys, drop, append, inplace, verify_integrity)
6008 if not found:
6009 missing.append(col)
6010
6011 if missing:
-> 6012 raise KeyError(f"None of {missing} are in the columns")
6013
6014 if inplace:
6015 frame = self
KeyError: "None of ['meta.vsn'] are in the columns"
Meteogram with Temperature, Dewpoint, and Winds#
This is what we call a meteogram, which is a timeseries of:
Temperature and Dewpoint (same plot)
Wind speed and direction (different plots)
The data is collected at 10 Hertz (10 observations per second) and averaged to 1 Hertz (1 per second) for the wind plots to illustrate turbulence!
Show code cell source
hv.Layout(plots).cols(1)
Wind Rose Plot#
This plot shows the freqency and direction of the winds, separated by the magnitude of the winds. This helps with identifying where the wind was coming from and how strong that wind was.
Show code cell source
WindDisplay = act.plotting.WindRoseDisplay(minute_ds, figsize=(6, 8), subplot_shape=(1,))
WindDisplay.plot(
'wind_direction', 'wind_speed', spd_bins=np.linspace(0, 20, 5), num_dirs=30, tick_interval=2, subplot_index=(0,)
)
plt.show()